/*
 * Copyright (C) 2012-2013  Romain DUBOIS
 * 
 * This file is part of NeMoS - Network and Modular Software
 * 
 * NeMoS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * NeMoS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with NeMoS.  If not, see <http://www.gnu.org/licenses/>.
 */
package nemos.swing;

import java.awt.Component;
import java.awt.Container;
import java.util.Map;
import java.util.Set;

/**
 * IComponentFactory : The component factory interface.
 * 
 * <p>
 * Services registered under this interface provide Swing {@link Component}s.
 * The managed component type ID must be registered in the
 * {@link #COMPONENT_TYPE} service property.
 * </p>
 * 
 * <p>
 * This interface main purpose is to ease the generation of Swing interfaces
 * from external resources, mainly textual files (plain, XML, ...). This is why
 * a {@link IComponentFactory} should handle parameters in a single
 * {@link String} form.
 * </p>
 * 
 * <p>
 * Some method implementations are optional. They are used to managed dynamic
 * properties : properties than can be modified after the component creation. A
 * {@link IComponentFactory} which only support creation parameters must always
 * return {@code false} to a call to the {@link #handleDynamicProperties()}
 * method.
 * </p>
 * 
 * @author Romain DUBOIS
 */
public interface IComponentFactory {

    /** The managed component type ID property name (String property) */
    String COMPONENT_TYPE = "nemos.swing.component.type"; //$NON-NLS-1$

    /**
     * Create a component in its default form.
     * 
     * @return A new component
     */
    Container createComponent();

    /**
     * Create a component using the specified parameters.
     * 
     * @param pInitParams
     *            The initialization parameters in a single String
     * @return A new component
     */
    Container createComponent(String pInitParams);

    /**
     * Create a component using the specified parameters.
     * 
     * @param pInitParams
     *            The initialization parameters map
     * @return A new component
     */
    Container createComponent(Map<String, ?> pInitParams);

    /**
     * Get the managed component class.
     * 
     * @return The managed component class
     */
    Class<? extends Container> getType();

    /**
     * If the factory supports properties modification/consultation after
     * creation.
     * 
     * @return If the factory handle dynamic properties.
     */
    boolean handleDynamicProperties();

    /**
     * (Optional) Get a property from a component created by this factory.
     * 
     * @param pProperty
     *            The property name
     * @param pComponent
     *            The component
     * @return The component property value
     * @throws UnsupportedOperationException
     *             If dynamic modifications are not handled by this factory
     * 
     * @see #handleDynamicProperties()
     */
    Object getProperty(String pProperty, Container pComponent) throws UnsupportedOperationException;

    /**
     * (Optional) Get the names of all properties associated to the components
     * created by this factory.
     * 
     * @return The managed type property names.
     * @throws UnsupportedOperationException
     *             If dynamic modifications are not handled by this factory
     * 
     * @see #handleDynamicProperties()
     */
    Set<String> getPropertyNames() throws UnsupportedOperationException;

    /**
     * (Optional) Get the type of a component property.
     * 
     * @param pProperty
     *            The property name
     * @return The property value type
     * @throws UnsupportedOperationException
     *             If dynamic modifications are not handled by this factory
     * 
     * @see #handleDynamicProperties()
     */
    Class<?> getPropertyType(String pProperty) throws UnsupportedOperationException;

    /**
     * (Optional) Change a component property value.
     * 
     * @param pProperty
     *            The property name
     * @param pValue
     *            The property value to set
     * @param pComponent
     *            The component to modify
     * @throws UnsupportedOperationException
     *             If dynamic modifications are not handled by this factory
     * 
     * @see #handleDynamicProperties()
     */
    void setProperty(String pProperty, Object pValue, Container pComponent)
            throws UnsupportedOperationException;
}
